local fileName = string.getModeName(...)
local NewListAdapterTool = class(fileName)

local Node_getPositionX = cc.Node.getPositionX
local Node_getPositionY = cc.Node.getPositionY
local ScrollView_isScrolling = ccui.ScrollView.isScrolling

-- params
-- list 		 	列表容器，不能为空
-- subPanelClass 	子renderClass，不能为空
-- initEndCb 		初始化完成回调,可以为空
function NewListAdapterTool:ctor( params )
	self._initEndCb = params.initEndCb
	self._subPanelClass = params.subPanelClass
	self._list = params.list
	self._list:removeAllChildren()

	self._innerContainer = self._list:getInnerContainer()
	-- self._innerContainer:setBackGroundColorType(1)
	-- self._innerContainer:setBackGroundColor( cc.c4b( 255,0,0,125 ) )
	self._innerContainer:setAnchorPoint( cc.p( 0, 1 ) )

	self._list:onNodeEvent("exit", function()
		if self._updateId then
			self._list:stopAction(self._updateId)
			self._updateId = nil
		end
		self._list:unscheduleUpdate()

		self._initEndCb = nil
		self._subPanelClass = nil
		self._cbFunc = nil
		self._isFirstInitFlag = true
		self._dataCountChanged = false
		self._listWidth = nil
		self._listHeight = nil
		self._isVertical = nil
		self._mNowPosx = nil
		self._mNowPosy = nil
		self._verticalInitPosY = nil
		self._verticalMaxPosY = nil
		self._topItemPosY = nil
		self._bomItemPosY = nil
		self._modelWidth = nil
		self._modelHeight = nil
		self._defCount = nil
		self._count = nil
		self._data = nil
		self._initEnd = false
		for i,v in ipairs( self._listChildrenDict ) do
			if cc.isAlive(v) then
				v:removeFromParent(true)
			end
		end
		self._listChildrenDict = nil

		self._list:removeAllChildren()
		self._list = nil
	end)

	-- 首次初始化标记
	self._isFirstInitFlag = true
	self._dataCountChanged = false

	-- 列表容器尺寸
	self._listWidth, self._listHeight = self._list:getContentSize2()

	-- 列表容器是否垂直滚动标记
	self._isVertical = (self._list:getDirection() == ccui.ListViewDirection.vertical)

	-- 当前innerContainer坐标
	self._mNowPosx = 0
	self._mNowPosy = 0

	-- 竖向滚动 上下边界item的Y坐标
	self._verticalInitPosY = 0
	self._verticalMaxPosY = 0

	-- 竖向滚动 按Y坐标排序时记录边界item Y坐标
	self._topItemPosY = 0
	self._bomItemPosY = 0


	-- 子render尺寸
	self._modelWidth = 0
	self._modelHeight = 0

	self._defCount = 0
	self._count = 0
	self._data = nil -- 数据源

	self._initEnd = false -- 初始化完成标记

	self._listChildrenDict = {} -- 子控件列表

	------------------------------------->>>>>>>>>> 以下
	-- 回弹时刷新一次render Pos
	-- 回弹过程中 isScrolling = false，不会_refreshContent。导致回弹过程中会出现位置没刷新的问题
	local function scrollViewEvent_1(sender, eventType)
		if eventType == ccui.ScrollviewEventType.bounceTop or eventType == ccui.ScrollviewEventType.bounceBottom then
			self:_refreshContent()
			return
		end
	end
	local function scrollViewEvent_2(sender, eventType)
		if eventType == ccui.ScrollviewEventType.bounceLeft or eventType == ccui.ScrollviewEventType.bounceRight then
			self:_refreshContent()
			return
		end
	end
	if self._isVertical then
		self._list:addEventListener(scrollViewEvent_1)
	else
		-- self._list:addEventListener(scrollViewEvent_2)
	end
	-------------------------------------<<<<<<<<<< 以上

	self:_initRenderList()
end

-- 子控件的处理回调
function NewListAdapterTool:setSubPanelCB(subPanelCb)
	self._cbFunc = subPanelCb
	if subPanelCb then
		for i,v in ipairs(self._listChildrenDict) do
			if cc.isAlive(v) then
				v:onBtnClick(self._cbFunc)
			end
		end
	end
end

-- 初始化子render列表
function NewListAdapterTool:_initRenderList()
	local modelSize = self._subPanelClass.create():getContentSize()
	--获取默认显示数量 +2
	local defCount = 0
	if self._isVertical then
		defCount = math.ceil(self._listHeight / modelSize.height) + 2
		self._modelHeight = modelSize.height
	else
		-- defCount = math.ceil(self._listWidth / modelSize.width) + 2
		-- self._modelWidth = modelSize.width
	end
	self._defCount = defCount

	-- 初始Container尺寸
	if self._isVertical then
		local contentHeight = self._defCount * modelSize.height
		local innerContainerWidth = self._innerContainer:getContentSize2()
		self._innerContainer:setContentSize(cc.size(innerContainerWidth,contentHeight))
	else
        -- local contentWidht = self._defCount * modelSize.width
        -- local _, innerContainerHeight = self._innerContainer:getContentSize2()
        -- self._innerContainer:setContentSize(cc.size(contentWidht,innerContainerHeight))
	end

	self._dataTempBeforeInitEnd = nil -- 初始化完成之前缓存的操作数据
	local index = 0
	local function delayInit()
		index = index + 1
		if index <= self._defCount then
			local temp = self._subPanelClass.create()
			temp:setName( "render" .. index )
			temp:onBtnClick( self._cbFunc )
			temp:setData( nil )

			table.insert( self._listChildrenDict, temp )
			self._innerContainer:addChild( temp )
			local _, innerContainerHeight = self._innerContainer:getContentSize2()
			if self._isVertical then
				temp:setAnchorPoint(cc.p(0,1))
				temp:setPositionY( innerContainerHeight - modelSize.height * (index - 1) )
			else
				-- temp:setAnchorPoint(cc.p(0,0))
				-- temp:setPositionX( modelSize.width * index )
			end
		else
			if self._delayInitId then
				self._list:stopAction(self._delayInitId)
				self._delayInitId = nil
			end

			self._initEnd = true
			if self._dataTempBeforeInitEnd then
				self:refreshList( self._dataTempBeforeInitEnd )
			end
			self._dataTempBeforeInitEnd = nil

			if self._initEndCb then
				self._initEndCb()
			end
		end
	end
	self._delayInitId = self._list:schedule(delayInit, 0)

	self._innerContainer:setPositionY( self._listHeight )
end

function NewListAdapterTool:_updatePerFrame( dt )
	if self._count < self._defCount - 2 then -- 实际个数不足以铺满scrollView
		return
	end
	if not ScrollView_isScrolling(self._list) then -- 非滚动状态？
		return
	end
	self:_refreshContent()
end

-- 排版调整具体逻辑
function NewListAdapterTool:_refreshContent()
	if self._isVertical then
		local nowPosy = Node_getPositionY( self._innerContainer )
		local _, containerHeight = self._innerContainer:getContentSize2()

		self:_sortList()
		if nowPosy > self._mNowPosy then
			--向上滑动
			local item = self._listChildrenDict[1] -- 最上方的item
			if cc.isDead(item) then
				return
			end
			local posy = Node_getPositionY( item )

			if posy > containerHeight - ( ( nowPosy - self._listHeight ) ) + self._modelHeight then -- 超过上边界
				local temp = self._bomItemPosY - self._modelHeight
				item:setPositionY( temp )

				-- 此处应该是根据数据位置索引刷新render
				local dataIndex = self._count - math.floor( temp/self._modelHeight ) + 1
				item:setData( { dataIndex,  self._data[ dataIndex ] } )
			end
		else
			--向下滑动
			local item = self._listChildrenDict[self._defCount] -- 最下方item
			if cc.isDead(item) then
				return
			end
			local posy = Node_getPositionY( item ) - ( self._verticalMaxPosY - nowPosy )

			if posy < 0 then
				local temp = self._topItemPosY + self._modelHeight
				item:setPositionY( temp )

				local dataIndex = self._count - math.floor( temp/self._modelHeight ) + 1
				item:setData( { dataIndex, self._data[ dataIndex ] } )
			end
		end
		self._mNowPosy = nowPosy
	-- else -- 横向滚动未调试、暂时不可用
	-- 	local nowPosx = self._innerContainer:getPositionX()

	-- 	nowPosx = math.min(0,nowPosx)
	--  local containerWidth = self._innerContainer:getContentSize2()
	-- 	nowPosx = math.max(-containerWidth,nowPosx)

	-- 	self:_sortList()
	-- 	if nowPosx > self._mNowPosx then
	-- 		--向右滑动
	-- 		for i = self._defCount - ItemAddCount+1 ,self._defCount do
	-- 			local item = self._listChildrenDict[i]
	-- 			local posx = item:getPositionX() + self._innerContainer:getPositionX()
	-- 			if posx > self._modelWidth * (self._defCount - ItemAddCount + 1)  then
	-- 				item:setPositionX( item:getPositionX() - (self._defCount) * self._modelWidth )

	-- 				local dataIndex = math.floor(item:getPositionX() / self._modelWidth)
	-- 				item:setData( self._data[ dataIndex ] )
	-- 			end
	-- 		end
	-- 	else
	-- 		--向左滑动
	-- 		for i = 1 ,ItemAddCount do
	-- 			local item = self._listChildrenDict[i]
	-- 			local posx = item:getPositionX() + self._innerContainer:getPositionX()
	-- 			if posx < -self._modelWidth then
	-- 				item:setPositionX( item:getPositionX() + (self._defCount ) * self._modelWidth )

	-- 				local dataIndex = math.floor(item:getPositionX() / self._modelWidth)
	-- 				item:setData( self._data[ dataIndex ] )
	-- 			end
	-- 		end
	-- 	end
	-- 	self._mNowPosx = nowPosx
	end
end

function NewListAdapterTool:refreshList( data )
	if not self._initEnd then
		self._dataTempBeforeInitEnd = data
		return
	end

	if self._updateId then
		self._list:stopAction(self._updateId)
		self._updateId = nil
	end

	self._data = data

	local oldCount = self._count
	self._count = #self._data -- 控件的个数
	self._dataCountChanged = oldCount ~= self._count

	--设置实际contentSize
	if self._isVertical then
		local contentHeight = self._count * self._modelHeight
		local innerContainerWidth = self._innerContainer:getContentSize2()
		self._innerContainer:setContentSize(cc.size(innerContainerWidth,contentHeight))

		self._list:setTouchEnabled( contentHeight > self._listHeight )
		self._list:setClippingEnabled( contentHeight > self._listHeight )
	else
		-- local contentWidht = self._count * self._modelWidth
		-- local _, innerContainerHeight = self._innerContainer:getContentSize2()
		-- self._innerContainer:setContentSize(cc.size(contentWidht,innerContainerHeight))

		-- self._list:setTouchEnabled( contentWidht > self._listWidth )
		-- self._list:setClippingEnabled( contentWidht > self._listWidth )
	end

	self:_initList()
	self._isFirstInitFlag = false
	self._updateId = self._list:schedule(handler(self, self._updatePerFrame), 0)
end

function NewListAdapterTool:_initList()
	local innerContainerWidth, innerContainerHeight = self._innerContainer:getContentSize2()
	if self._isVertical then
		self._mNowPosy = Node_getPositionY( self._innerContainer )
		self._verticalInitPosY = self._mNowPosy
		self._verticalMaxPosY = innerContainerHeight
	else -- 横向滚动暂未调试，不可用
	end

	-- 先按 坐标 降序排列
	self:_sortList()
	-- 根据 pos 填充数据
	if self._isVertical then
		for i = 1, self._defCount do
			local itemTemp = self._listChildrenDict[i]
			if cc.isAlive(itemTemp) then
				local itemPosY = itemTemp:getPositionY()
				if self._isFirstInitFlag or -- 首次初始化?
				  self._dataCountChanged then -- 数据个数发生变化
					-- 重置滚动列表位置
					if cc.isAlive(self._innerContainer) then
						self._innerContainer:setPositionY(self._listHeight)
					end
					itemPosY = innerContainerHeight - self._modelHeight*(i-1)
				end
				itemTemp:setPositionY(itemPosY)
				local dataIndex = self._count - math.floor(itemPosY / self._modelHeight) + 1
				itemTemp:setData({dataIndex, self._data[dataIndex]})
			end
		end
	end
end

-- 具体的排序函数
function NewListAdapterTool:_sortListFunc( item1,item2 )
	if self._isVertical then
		return Node_getPositionY(item1) > Node_getPositionY(item2)
	else
		-- return Node_getPositionX(item1) > Node_getPositionX(item2)
	end
end

--将各个item按方向坐标从大到小
function NewListAdapterTool:_sortList()
	table.sort( self._listChildrenDict, handler( self, self._sortListFunc ) )

	if self._isVertical then
		if cc.isAlive(self._listChildrenDict[1]) then
			self._topItemPosY = Node_getPositionY(self._listChildrenDict[1])
		end
		if cc.isAlive(self._listChildrenDict[self._defCount]) then
			self._bomItemPosY = Node_getPositionY(self._listChildrenDict[self._defCount])
		end
	end
end

return NewListAdapterTool
